<?php
/*
 * @Date: 2022-12-02 10:48:54
 * @LastEditors: 搬铁的码农 dong2406@126.com
 * @LastEditTime: 2024-09-03 15:30:12
 */

namespace Ldy\Grid;

use Ldy\Model as LdyModel;
use Ldy\Lib\Grid;

class Model{

    /**
     * LdyModel执行条件查询后变为 thinkModel
     *
     * @var LdyModel
     */
    protected $model;

    protected $originalModel;

    protected $grid;

    protected $queries;

    protected $column;

    protected $param;

    protected $isSetField = false;//数据字段

    protected $notPage = false; //不分页获取全部数据

    protected $mainTablePrefix = '';//主表联表前缀

    protected $fieldPrefix = []; //前缀和字段对照表  字段=>前缀

    /**
     * 分页信息
     *
     * @var array
     */
    protected $page = [
        "total"=>0,     //总条数
        "page_size"=>20,//页大小
        "page_num" => 0,//总页数
        "page_up" => 0,//上一页
        "page_next" => 0,//下一页
        "page_current"=> 1,//当前页
    ];

    public function __construct(LdyModel $model, Grid $Grid = null)
    {
        $this->model = $model;

        $this->originalModel = $model;
        
        $this->grid = $Grid;

        $this->queries = [];

        $this->param =  request()->get();

        if(isset($this->param['page'])) $this->page['page_current'] = $this->param['page'] ? intval($this->param['page']):1;
        if(isset($this->param['page_size'])) $this->page['page_size'] = intval($this->param['page_size']);

    }

    public function dataModel(){
        return $this->model;
    }

    public function get(){

        $this->column = [];
        
        //模型字段 不做过滤了
        // $modelFields = $this->model->getTableFields();
        //联表参数
        $joinTableParam = $this->grid->joinTableParam;
        
        $pk = $this->model->getPk();
        $autoPk = true;
        $fields = [];

        foreach($this->grid->column as $key => $item) {
            
            $prop = $item['prop'];
            //设置列表头数据 删除前缀给前台用的 要不和 列表数据字段名不对应，排序时再补回去
            if(!isset($item['hide'])) {
                if(strpos($prop,'.')!== false) $item['prop'] = explode('.', $prop)[1];
                $this->column[] = $item;
            }

            //qs.id
            if($prop == $pk || strpos($prop, $pk) !== false) $autoPk = false;

            //保存带前缀的字段和前缀，创建一个对照表 联表字段 带 . 号的字段处理
            $this->joinTableFieldHandle($prop);

            $fields[] = $prop;

            //设置查询元素数据
            // if(isset($this->param[$key])) $this->query[$key] = $this->param[$key];
        }
        
        if($autoPk) $fields[] = $pk;
        
        //没有手动设置字段时，自动设置
        if(!$this->isSetField) $this->setQueries('field',[$fields]);

        //多表连接 支持 leftJoin、rightJoin 、join(内连)
        if(!empty($joinTableParam)) {
            //设置模型表别名，就是主表, 有调用 alias 方法设置后 不再自动设置表别名
            if(!$this->grid->manualAlias) $this->setQueries('alias',[$this->mainTablePrefix]);
            // $this->setQueries('field',[$joinTableField])->setQueries('leftJoin', $leftJoin);
            foreach($joinTableParam as $item) $this->setQueries($item['type'], $item['param']);
        }     

        if($this->grid->outTree) return $this->model->trees([], $this->grid->queryElement);
    
        //设置条件，排序
        $this->setWhere()->order();

        //执行sql
        foreach($this->queries as $query){
            $this->model = call_user_func_array([$this->model, $query['method']], $query['arguments']);
        } 
		

		$pageSite = intval($this->page['page_size']);
        $page = intval($this->page['page_current']);
         //分页
        if(!$this->notPage) {
            //设置分页前统计所有数据条数再设置分页
            $this->setPage($this->model);
            //设置分页
            $this->model = $this->model->page($page, $pageSite);
        }


        $data = $this->model->select();

        return $data;
    }

    /**
     * 设置排序
     *
     * @return $this
     */
    public function order($field = '', $order= ''){
        $getOrder = isset($this->param['order']) ? $this->param['order']:null;
        if(empty($getOrder) && !empty($field)) $getOrder = $field."|".$order;
        if(empty($getOrder)) return false;

        list($field, $o) = explode('|', $getOrder);
        if($o == 'null') return false;

        //有前缀就补上
        $this->setFieldPrefix($field);

        $this->setQueries('order',[$field, $o]);

        return $this;
    }
    /**
     * 查询条件
     *
     * @return Object
     */
    private function setWhere(){
        
        foreach($this->grid->queryElement as $item){

            $field =  $item['field'];

            if($item['type'] == 'quick_search'){
                
                $val = '';
                $tmpField = [];
                $searchField = '__quick_search';
                foreach($field as $f) {
                    if($f['name'] != '__quick_search') $tmpField[] = $f['name'];

                    if(isset($this->param[$f['name']])){
                        $val = trim($this->param[$f['name']]);
                        $searchField = $f['name'];
                    }
                }

                if($val === null || $val === '') continue;

                $this->setFieldPrefix($searchField);
                $pk = $this->model->getPk();

                if($searchField == '__quick_search'){
                    $str = implode("|", $tmpField);
                    $this->setQueries('where', [$str, 'like', '%'.$val.'%']);
                }else if($searchField == $pk || strpos($searchField, $pk)){
                    //主键查询
                    $this->setQueries('where', [$searchField, $val]);
                }else{
                    $this->setQueries('where', [$searchField, 'like', "%{$val}%"]);
                }
                
            }else{
                $val = isset($this->param[$field]) ? trim($this->param[$field]):null;
                if($val === null || $val=='ALL' || $val ==='') continue;
                
                $val = $val == 'empyt' ? '':$val;

                $this->setFieldPrefix($field);

                if(isset($item['filter'])){
                    $filter = $item['filter'];
                    if ($filter instanceof \Closure) {
                        //闭包自定义处理
                        call_user_func($filter,$this,$val);
                    }elseif($filter == 'date_range' && !empty($val)){
                        //时间范围搜索
                        [$start, $end] = explode(',',$val);
                        
                        $start = strtotime($start);
                        $end = strtotime($end)  + 24*60*60;
            
                        // $model = $model->where($field,'>=', $start)->where($field,'<=', $end);
                        $this->setQueries('where', [$field,'>=', $start])->setQueries('where', [$field,'<=', $end]);
                    }elseif($filter == 'like'){
                        $this->setQueries('where', [$field, 'like', "%{$val}%"]);
                    }elseif(is_array($filter)){
                        //数组模式
                        // $model = $model->where($field, $filter[$val], $val);
                        $this->setQueries('where', [$field, $filter[$val], $val]);
                    }else{
                        $this->setQueries('where', [$field, $filter, $val]);
                    }
                }else{
                    // $model = $model->where($field, $val);
                    $this->setQueries('where', [$field, $val]);
                }
               
            }
        }

        return $this;
    }

    public function field(String $fields){
        $this->isSetField = true;
        $this->setQueries('field',[$fields]);
        return $this;
    }

    public function notPage(){
        $this->notPage = true;
        return $this;
    }

    public function getPage(){
        return $this->page;
    }

    public function getColumn(){
        return $this->column;
    }

    public function setPageSize($val){
        $this->page['page_size'] = $val;
        return $this;
    }

    private function setPage($model){
        if($this->grid->_not_first && !$this->grid->_is_query) return false;

        $count = $model->count();
        
        $count = $count ? $count:0;
        $this->page['total'] = $count;
        $this->page['page_num'] = ceil($count / $this->page['page_size']);

        $this->page['page_up'] = $this->page['page_current']-1;
        $this->page['page_next'] = $this->page['page_current'] +1;

        if($this->page['page_current'] == 1 || $this->page['page_current'] == 0) $this->page['page_up'] = 1;

        if($this->page['page_current'] > $this->page['page_num']) $this->page['page_current'] = $this->page['page_num'];
    }

    public function __call($method, $arguments)
    {
        $this->setQueries($method, $arguments);

        return $this;
    }


    private function setQueries($method, $arguments = []){
       
        $this->queries[] = [
            'method'    => $method,
            'arguments' => $arguments,
        ];

        return $this;
    }

     /**
     * 保存带前缀的字段和前缀，创建一个对照表 联表字段 带 . 号的字段处理
     *
     * @param [type] $prop
     * @return void
     */
    private function joinTableFieldHandle($prop){

        //没有.号的不处理
        if(strpos($prop, '.') === false) return false;

        [$prefix, $field] = explode('.', $prop);
        $this->fieldPrefix[$field] = $prefix;
        //规定第一个字段的前缀就是主表别名
        if(empty($this->mainTablePrefix)) $this->mainTablePrefix = $prefix;
        
    }

    /**
     * return string
     */
    private function setFieldPrefix(String &$field){
        $field = (isset($this->fieldPrefix[$field]) && $this->fieldPrefix[$field] ? $this->fieldPrefix[$field].'.':'').$field;
    }
}